#include<iostream>
#include<queue>
#include<pthread.h>
using namespace std;


#define MAX_CAP 5
template<class T>
class BlockQueue
{
public:
  BlockQueue() :_cap(MAX_CAP)
  {
    pthread_mutex_init(&_mtx,NULL);
    pthread_cond_init(&_con,NULL);
    pthread_cond_init(&_pro,NULL);
  }
  ~BlockQueue()
  {
    pthread_mutex_destroy(&_mtx);
    pthread_cond_destroy(&_con);
    pthread_cond_destroy(&_pro);
  }
  void push(const T& val)
  {
    pthread_mutex_lock(&_mtx);
    while(isFull())
    {
      pthread_cond_wait(&_pro,&_mtx);
    }
    task_queue.push(val);
    pthread_cond_signal(&_con);
    pthread_mutex_unlock(&_mtx);
  }
  void pop(T* val)
  {
    pthread_mutex_lock(&_mtx);
    while(empty())
    {
      pthread_cond_wait(&_con,&_mtx);
    }
    *val = task_queue.front();
    task_queue.pop();
    pthread_mutex_unlock(&_mtx);
    pthread_cond_signal(&_pro);
  }
  bool isFull() const 
  {
    return _cap == task_queue.size();
  }
  bool empty() const 
  {
    return task_queue.empty();
  }
private:
  pthread_cond_t _con;
  pthread_cond_t _pro;
  queue<T> task_queue;
  int _cap;
  pthread_mutex_t _mtx;
};
